"""
Contains various SPM test cases.
"""
import unittest as ut

import basicVdsTest as vdst
from confUtils import Validate
import vdsClient as vdsc
from storageConnectionTestUtils import eStorageType, disconnectFromStorage, connectToStorage, validateConnections, CONNECTIONS_OPTION_DEFAULT
from storageDomainTestUtils import eDomainClass, generateDomainTargets, destroyDomainTargets
from testUtils import cleanVdsm
from spmTestUtils import eSpmStatus

__commonConfig__ = {
    "VdsUri1" : {"default" : "http://server:54321"},
    "Connections" : {"default" : CONNECTIONS_OPTION_DEFAULT, "validator" : validateConnections},
    "DomainClass1" : {"default" : "data", "validator" : eDomainClass.parse},
    "Domain1" : {"default" : "GUID, GUID", "validator" : Validate.list},
    "StorageType1": {"default" : "nfs", "validator" : eStorageType.parse},
    "HostID1" : {"default" : 7, "validator" : Validate.int},
    "Pool1Key" : {"default" : "NFSKEY"}
}

class SpmTestCaseBase(vdst.BasicVDSTest):
    """
    Contains common, factors shared by all SPM test cases.
    """
    #For convenience. I didn't put it in the base class because I didn't want to commit.
    mycfg = property(lambda self: self.cfg[self.__class__.__name__])
    @classmethod
    def getConfigTemplate(cls):
        return { cls.__name__ : __commonConfig__ }

    def setUp(self):
        #Setup client
        self.client = vdsc.VDSClient()
        self.client.setURI(self.mycfg["VdsUri1"])

        #Make sure env is clean
        resp = self.assertVdscOK(self.client.getConnectedStoragePoolsList())
        self.assertTrue(len(resp['poollist']) == 0, "VDSM is connected to a pool. Dirty env. Bailing out.")

        #Handle storage configuration
        connectToStorage(self.client, self.mycfg["Connections"])
        self.domainTarget1 = generateDomainTargets(self.client, self.mycfg["Connections"], [self.mycfg["Domain1"]])[0]

        #setup test variables
        self.sdUUID = self.client.newUUID()
        self.spUUID = self.client.newUUID()

        #Create the tmp domain
        self.assertVdscOK(
            self.client.createStorageDomain(self.mycfg["StorageType1"], self.sdUUID,
                "Storage Domain 1", self.domainTarget1, self.mycfg["DomainClass1"]
            )
        )

        #Create tmp pool
        self.assertVdscOK(
            self.client.createStoragePool(self.spUUID, "Swimming Pool", self.sdUUID, [self.sdUUID], 1)
            )

        self.assertVdscOK(
            self.client.connectStoragePool(self.spUUID, self.mycfg["HostID1"], self.mycfg["Pool1Key"])
            )

    def tearDown(self):
        cleanVdsm(self.client, self.mycfg["HostID1"], self.mycfg["Connections"])

class SpmStartWithWrongParams(SpmTestCaseBase):
    """
    Test that SPM fails to start if given bad params.
    """
    def InvalidPool(self):
        self.assertVdscFail(self.client.spmStart("Twisting by the pool", -1, -1, -1, False))

    def WrongPrevVars(self):
        taskid = self.assertVdscOK(self.client.spmStart(self.spUUID, 999999, 9999999, 0, False))['uuid']
        self.assertVdscTaskFail(self.client, taskid)

class SpmStart(SpmTestCaseBase):
    """
    Test that SPM starts if given a valid pool and that the status is changed properly.
    """
    def test(self):
        status = self.assertVdscOK(self.client.getSpmStatus(self.spUUID))['spm_st']
        self.assertEquals(status['spmStatus'], eSpmStatus.Free,
            "SPM in wrong sate before start. Expected '%s' was '%s'" % (eSpmStatus.Free, status['spmStatus']))
        taskid = self.assertVdscOK(self.client.spmStart(self.spUUID, -1, -1, -1, False))['uuid']
        self.assertVdscTaskOK(self.client, taskid)
        status = self.assertVdscOK(self.client.getSpmStatus(self.spUUID))['spm_st']
        self.assertEquals(status['spmStatus'], eSpmStatus.Running,
            "SPM in wrong sate after start. Expected '%s' was '%s'" % (eSpmStatus.Running, status['spmStatus']))

class StartTheSameSpmTwice(SpmTestCaseBase):
    def test(self):
        taskid = self.assertVdscOK(self.client.spmStart(self.spUUID, -1, -1, -1, False))['uuid']
        self.assertVdscTaskOK(self.client, taskid)

        self.assertVdscFail(self.client.spmStart(self.spUUID, -1, -1, -1, False))

class SpmStop(SpmTestCaseBase):
    """
    Test that SPM stops after
    """
    def setUp(self):
        SpmTestCaseBase.setUp(self)
        taskid = self.assertVdscOK(self.client.spmStart(self.spUUID, -1, -1, -1, False))['uuid']
        self.assertVdscTaskOK(self.client, taskid)

    def test(self):
        self.assertVdscOK(self.client.spmStop(self.spUUID))
        status = self.assertVdscOK(self.client.getSpmStatus(self.spUUID))['spm_st']
        self.assertEquals(status['spmStatus'], eSpmStatus.Free,
            "SPM in wrong sate after stop. Expected '%s' was '%s'" % (eSpmStatus.Free, status['spmStatus']))

def suite():
    tests = {
        SpmStart : ["test"],
        SpmStop : ["test"],
        StartTheSameSpmTwice : ["test"],
        SpmStartWithWrongParams : ["InvalidPool", "WrongPrevVars"]
    }

    resSuite = ut.TestSuite()
    for testcase, methods in tests.iteritems():
        resSuite.addTests(map(testcase, methods))

    return resSuite

validateConfig = lambda cfg : vdst.validateSuiteConfig(suite(), cfg)
